package com.peking.donations.plugins.oauth2.client.wechart;

import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.http.converter.FormOAuth2AccessTokenMessageConverter;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;

import static org.springframework.security.oauth2.common.OAuth2AccessToken.*;

/**
 * @author Vigor Yuan
 */
public class WechartOAuth2AccessTokenMessageConverter extends FormOAuth2AccessTokenMessageConverter {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Charset charset = DEFAULT_CHARSET;

    @Override
    protected OAuth2AccessToken readInternal(Class<? extends OAuth2AccessToken> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException {
        MediaType contentType = inputMessage.getHeaders().getContentType();
        Charset charset = (contentType.getCharSet() != null ? contentType.getCharSet() : this.charset);
        String body = StreamUtils.copyToString(inputMessage.getBody(), charset);

        JSONObject jsonObject = JSONObject.parseObject(body);

        DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(jsonObject.getString(ACCESS_TOKEN));

        token.setExpiration(new Date(System.currentTimeMillis() + (jsonObject.getLong(EXPIRES_IN) * 1000L)));

        String refresh = jsonObject.getString(REFRESH_TOKEN);
        DefaultOAuth2RefreshToken refreshToken = new DefaultOAuth2RefreshToken(refresh);
        token.setRefreshToken(refreshToken);

        Set<String> scope = new TreeSet<>();
        StringTokenizer tokenizer = new StringTokenizer(jsonObject.getString(SCOPE), " ,");
        scope.add(tokenizer.nextToken());
        token.setScope(scope);

        Map<String, Object> addtional = new HashMap<>();
        addtional.put("openid", jsonObject.getString("openid"));
        token.setAdditionalInformation(addtional);
        return token;
    }
}
